import { Component, Inject, OnInit } from '@angular/core';
import {
  combineLatest,
  concat,
  defer,
  empty,
  filter,
  from,
  fromEvent,
  generate,
  interval,
  map,
  merge,
  observable,
  Observable,
  Observer,
  range,
  repeat,
  repeatWhen,
  timer,
  zip,
  count,
  min,
  max,
  reduce,
  every,
  find,
  findIndex,
  isEmpty,
  defaultIfEmpty,
  first,
  last,
  take,
  takeLast,
  takeWhile,
  skip,
  takeUntil,
  throttleTime,
  debounceTime,
  auditTime,
  pluck,
  groupBy,
  partition,
  scan,
  mergeScan,
  catchError,
  retry,
  retryWhen, delay, Subject, publish, share
} from "rxjs";
import { of } from 'rxjs';
import { DOCUMENT } from '@angular/common';

@Component({
  selector: 'app-welcome',
  templateUrl: './welcome.component.html',
  styleUrls: ['./welcome.component.css']
})
export class WelcomeComponent implements OnInit {

  constructor(@Inject(DOCUMENT) private document: Document) {



  }

  ngOnInit() {



  }

  p25(){
    let source$=of(1,2,3);
    source$.subscribe((v)=>{
      console.log(v);
    })
  }

  p26(){
    const onSubscribe=(observer:Observer<any>)=>{
      // observer.next(1);
      // observer.next(2);
      // observer.next(3);

      //p28
      // let number=1;
      // const handle=setInterval(()=>{
      //   observer.next(number++);
      //   if(number>3){
      //     clearInterval(handle)
      //   }
      // },1000)

      //p29
      let number=1;
      const handle=setInterval(()=>{
        observer.next(number++);
        if(number>10){
          clearInterval(handle);
          observer.complete();
        }
        if(number==17){
          observer.error('can not equal seven');
        }
      },1000);

    };



    const source$=new Observable(onSubscribe);

    const theObserver={
      next:(item:any)=>{console.log(item)},
      complete:()=>{console.log('No More Data')},
      error:(err:any)=>{console.error(err)}
    }


    // source$.subscribe(
    //   theObserver
    // )

    source$.subscribe(
      item=>{console.log(item)},
      error => {console.error(error)},
      ()=>{console.log('No More Data')}

    );

  }


  p34(){

    const source$=new Observable((observer)=>{
      let number=1;
      const handle=setInterval(()=>{
        observer.next(number++);
        if(number>10){
          clearInterval(handle);
          observer.complete();
        }
        if(number==17){
          observer.error('can not equal seven');
        }
      },1000);
    });

    const subscription=source$.subscribe((item:any)=>{
      console.log(item);
    })


    setTimeout(()=>{
      console.log('unscribe');
      subscription.unsubscribe();
    },3500)
  }



  p38(){
    // const onSubscribe=(observe:any)=>{
    //   observe.next(1);
    //   observe.next(2);
    //   observe.next(3);
    // }
   // const onSubscribe=from([1,2,4])

    //const source$=Observable.create(onSubscribe);
    const  source$=from([1,2,3]);
    source$.pipe(map((x:number)=>x*x))
     .subscribe((r:number)=>{
        console.log(r);
      })

  }


  p43(){
    const source$=from([1,2,3,4]);
    const result$=source$
      .pipe(
        filter(x=>x%2===0),
        map(x=>x*2))
    result$.subscribe((r:any)=>{
      console.log(r);
    })
  }

  rangefun(){
    const source$=range(1.1,100);
    source$
      .pipe(map(x=>x+0.1))
      .subscribe((r:number)=>{

      console.log(r);
    })
  }

  generatefun(){
    const source$=generate(
      2,
      value=>value<10,
      value=>value+2,
      value=>value*value
    );
    source$
      .pipe(repeat(3))
      .subscribe((r:number)=>{
      console.log(r);
    })


  }

  emptyfun(){
    const source$=empty();
    source$.subscribe((r:any)=>{
      console.log(r);
    }
    ,
      error => console.error(error),
      ()=>console.log('complete')
    )
  }

  intervalfun(){
    const source$=interval(1000);
    source$.subscribe((r:any)=>{
      console.log(r);
    })
  }

  timefun(){
    const source$=timer(2000,2000);
    source$.subscribe((r:any)=>{
      console.log(r);
    })
  }

  fromfunc(){
    const source$=from('abc');
    source$.subscribe((r)=>{
      console.log(r);
    })
  }

  fromforpromise(){
    const promise=Promise.resolve('good');
    const source$=from(promise)
    source$.subscribe((r:any)=>{
      console.log(r);
    })
  }


  repeateWhenFun(){
    const source$=of([1,2,3]);
    const repeate$=source$
      .pipe(
        repeatWhen(()=>interval(1000))
      )
      .subscribe((r:any)=>{
      console.log(r);
    })
  }

  deferfun(){
    const objectfactory$=()=>of(['1',2]);
    const source$=defer(objectfactory$)
    source$.subscribe((r:any)=>{
      console.log(r);
    })
  }




  concatfunc(){
    const source1$=of(1,2,3);
    const source2$=of(4,5,6);
    const result$=concat(source1$,source2$);
    result$.subscribe((r:number)=>{
      console.log(r);
    })
  }


  mergedFun(){
    const source1$=timer(0,1000).pipe(
      map((x:any)=>x+'A')
    );
    const source2$=timer(500,1000).pipe(
      map((x:number)=>x+'B')
    );
    const merged$=merge(source1$,source2$);

   merged$.subscribe((r)=>{
     console.log(r)
   },
     error => console.error(error),
     ()=>console.log('complete')
     )

  }

  zipFun(){
    const source1=of(1,2,3);
    const source2=of('a','b','c');
    const ziped$=zip(source1,source2);
    ziped$.subscribe(item=>console.log(item),
      error => console.error(error),
      ()=>{console.log('complete')}
      )
  }


  combineLatestFun(){
    const source1$=timer(1000,1000);
    const source2$=timer(2000,1000);
    const result$=combineLatest(source1$,source2$);
    result$.subscribe(
      console.log,
      null,
      ()=>{console.log('complete')}
    )

  }


  startWatch(){
    const event$=fromEvent(this.document.body,'click');
    const x$=event$.pipe(map(x=>x.AT_TARGET))
    const y$=event$.pipe(map(y=>y.BUBBLING_PHASE))
    const result$=combineLatest(x$,y$)
    result$
      .pipe(map((x,y)=>'x:'+x+"y"+y))
      .subscribe(
        console.log,
        null,
        ()=>{console.log('complete')}
      )

  }


  countfun(){
    const source1$=of(1,2,3);
    const  souce2$=of(4,5,6);
    const reslut$=concat(source1$,souce2$);
    reslut$.pipe(count())
      .subscribe(
        console.log
      )
  }

  minAndMax(){
    const source$=of(
      {name:'a',age:23},
      {name:'b',age:25},
      {name:'c',age:36}
    )

    source$.pipe(
      max((a,b)=>a.age-b.age) //min与max使用相同方法
    )
      .subscribe(
        console.log
      )
  }

  reducefun(){
    const source =range(1,100);
    source.pipe(
      reduce(
        (acc,current)=>acc+current
      )
    )
      .subscribe(
        console.log
      )
  }

  everyfun(){
    const source$ = range(1,100);
    source$
      .pipe(
        every((x)=>x<10)
      )
      .subscribe(
        console.log
      )
  }

  findfunc(){
    const source$=of(3,1,4,1,5,9);
    source$
      .pipe(
        findIndex((x)=>x%2===0)
      )
      .subscribe(
        console.log
      )
  }

  isEmptyFUn(){
    const source$=empty();
    source$
      .pipe(
        defaultIfEmpty('is empty')
      )
      .subscribe(
        console.log
      )
  }


  firstFun(){
    const source$=of(3,2,9,5,6);
    source$
      .pipe(
        last(x=>x%2===0)
      )
      .subscribe(
        console.log,
        error => console.error('未找到错误'),
        ()=>{console.log('complete')}
      )
  }

  takefun(){
    const source$=range(1,100);
    source$
      .pipe(
        skip(3),
        takeWhile(x=>x%2===0)
      )
      .subscribe(
        console.log
      )
  }

  throttletime(){
    const source$=interval(1000);
    const result$=source$.pipe(
      //throttleTime(2000)
      filter(x=>x%3===0),
      debounceTime(2000)//延时输出
    )
      .subscribe(
        console.log
      )
  }

  auditTimeFun(){
    const source$=interval(1000);
    const  result$=source$.pipe(
      auditTime(2000)
    )
      .subscribe(
        console.log
      )
  }



  pluckfun(){
  const source$=  of(
      {name:'a',version:'v1'},
      {name:'b',version:'v2'},
      {name:'c',version:'v3'},
      {name:'d',version:'v4'},
    )
    source$
      .pipe(
        pluck('name')
      )
      .subscribe(
        console.log
      )

  }


  groupbyfun(){
    const source$=range(1,100);
    const groupbystream$=source$.pipe(
      groupBy(x=>x%2)
    )
      .subscribe(
        console.log
      )
  }


  partitionfun(){
    // const source$=  of(
    //   {name:'a',version:'v1',age:12},
    //   {name:'b',version:'v2',age:13},
    //   {name:'c',version:'v3',age:14},
    //   {name:'d',version:'v4',age:15},
    // )
    // const [even$,odd$]=source$
    //   .pipe(
    //    // partition(x=>x%2===0) //错误位置
    //   )
    //
    // even$.subscribe(
    //  console.log
    // )
    //
    // odd$.subscribe(
    //   console.log
    // )
  }


  scanfun(){
    const source$=range(1,100)
    const reslult=source$.pipe(
      scan((a,v)=>{
        return a+v;
      })
      // mergeScan((a,v)=>{
      //   return of(a+v);
      // },0)
    )

    reslult.subscribe(
      console.log
    )
  }


  throwUnLuckyNumber=(value:number)=>{

    if(value===4){
      throw new Error('unlucky number 4')
    }
    return value;
  }

  catchfun(){
    const source$=range(1,10);
    const error$=source$.pipe(
      map(this.throwUnLuckyNumber),
      //retry(2),
      retryWhen(errors => errors.pipe(delay(1000), take(2))),
      catchError((err,caught)=>of('error occure'))

    )
      .subscribe(
        console.log
      )

  }


  finalfun(){
    try {
      this.catchfun()
    } catch (e) {
      console.error(e);
    } finally {
      console.log('finally');
    }
  }

  subjectfun(){
    const tick$=interval(1000)
      .pipe(
        take(6)
      )

    const subject=new Subject();
    tick$.subscribe(
      subject
    )
    subject.subscribe(
      value => console.log('observer one'+value)
    )
    setTimeout(()=>{
      subject.subscribe(value => console.log('observer two'+value))
    },2000)
  }

  punishfun(){

    const tick$=range(1,100);
    // tick$.pipe(
    //   publish(@sharedtick$)
    // )

  }



  sharefun(){
    const tick$=interval(1000).pipe(
      take(3),
      share()
    )
    tick$.subscribe(value => {console.log('obOne  '+value)})

    setInterval(()=>{
      tick$.subscribe(value => {console.log('obTwo  '+value)})
    },2000)
  }

}
